package com.zwr.pattern.sequence;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 比如，必须先 2 后 1 打印
 */
public class FixedSequence {
}

/**
 * wait notify 版
 */
class WaitNotifyVersion{
    // 用来同步的对象
    static final Object obj = new Object();

    // t2 运行标记， 代表 t2 是否执行过
    static boolean t2runed = false;

    public static void main(String[] args) {

        Thread t1 = new Thread(() -> {
            synchronized (obj){
                if(!t2runed){
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(1);
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (obj){
                System.out.println(2);
                t2runed=true;
                obj.notifyAll();
            }

        });

        t1.start();
        t2.start();
    }
}

/**
 * park unpark 版
 */
class ParkUnparkVersion{

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            LockSupport.park();
            System.out.println(1);
        });
        Thread t2 = new Thread(() -> {
            System.out.println(2);
            LockSupport.unpark(t1);
        });

        t1.start();
        t2.start();


    }
}

/**
 * lock 版本
 */
class LockVersion{
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    // t2 运行标记， 代表 t2 是否执行过
    static boolean t2runed = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(()->{

            while (!t2runed){
                lock.lock();
                try {
                    condition.await();
                    System.out.println(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        });

        Thread t2 = new Thread(()->{

            lock.lock();
            try {
                System.out.println(2);
                t2runed=true;
                condition.signal();
            }finally {
                lock.unlock();
            }


        });
        t1.start();
        t2.start();


    }
}
